package ccm.component.menu;

import ccm.common.Buffer;
import ccm.common.CCMConfigManager;
import ccm.component.override.JButton;
import ccm.component.override.JLabel;
import ccm.component.override.JSpinner;

import javax.swing.*;
import java.awt.*;

abstract class NumberMenuItemJPanel extends SingleMenuItem implements ValuableMenuItem
{
    final protected JLabel valueJLabel;
    final protected JSpinner valueJSpinner;
    final protected JButton sendJButton;
    protected Number value;

    protected NumberMenuItemJPanel(DelegateSenderInterface sender,Component[] rightMenu,String saveArgPrefix,int dataIndex,boolean canModify,ScnsType type,int page,String name)
    {
        super(sender,rightMenu,saveArgPrefix,dataIndex,canModify,type,page,name);
        valueJLabel=new JLabel();
        valueJLabel.setOpaque(true);
        add(valueJLabel);

        valueJSpinner=new JSpinner(new SpinnerNumberModel());
        add(valueJSpinner);

        sendJButton=new JButton("发送");
        sendJButton.addActionListener(e->
        {
            updateColor();
            if(e.getSource()==sendJButton)
            {
                needSendValueFlag=true;
            }
        });
        add(sendJButton);

        loadConfig();
        valueJSpinner.addChangeListener(e->storeConfig());
        valueJSpinner.addChangeListener(e->updateColor());
        valueJSpinner.addChangeListener(e->
        {
            if(autoSendJCheckBox.isSelected())
            {
                needSendValueFlag=true;
            }
        });
        setCanModify(canModify);
        Dimension dimension=new Dimension(100,(int)(valueJLabel.getFont().getSize()*1.2+10));
        valueJLabel.setPreferredSize(dimension);
        valueJSpinner.setPreferredSize(dimension);
        valueJLabel.setBorder(BorderFactory.createEtchedBorder());
        valueJSpinner.setBorder(BorderFactory.createEtchedBorder());
    }

    final protected void updateColor()
    {
        if(isCanModify()&&!sameAsValue(valueJSpinner.getValue()))
        {
            valueJLabel.setForeground(Color.RED);
        }
        else
        {
            valueJLabel.setForeground(null);
        }
    }

    @Override
    final protected String storeConfig()
    {
        final String prefix=super.storeConfig();
        CCMConfigManager.setNumber(prefix+"/value",(Number)valueJSpinner.getValue());
        return prefix;
    }

    @Override
    final public String loadConfig()
    {
        final String prefix=super.loadConfig();
        if(valueJSpinner!=null)
        {
            valueJSpinner.setValue(CCMConfigManager.setNumberIfAbsent(prefix+"/value",0));
            updateColor();
        }
        return prefix;
    }

    @Override
    final public void setCanModify(boolean canModify)
    {
        super.setCanModify(canModify);
        if(valueJSpinner!=null)
        {
            valueJSpinner.setVisible(canModify);
        }
        if(sendJButton!=null)
        {
            sendJButton.setVisible(canModify);
        }
    }

    @Override
    final public void setStep(float step)
    {
        if(step==0)
        {
            return;
        }
        ((SpinnerNumberModel)valueJSpinner.getModel()).setStepSize((step));
    }

    @Override
    final public void loadValueToInput()
    {
        valueJSpinner.setValue(value);
        updateColor();
        storeConfig();
    }

    @Override
    final public void requestValue()
    {
        System.out.println("requestValue(0X1E) "+dataIndex);
        int start=0;
        byte[] buf=new byte[64];
        start=Buffer.setUint16(buf,start,dataIndex);
        addTailAndSend(buf,start,0X1E);
    }

    final public void setValue(Object value)
    {
        if(value instanceof Number)
        {
            if(this.value==null||!sameAsValue(value))
            {
                valueJLabel.setBackground(Color.YELLOW);
            }
            else
            {
                valueJLabel.setBackground(null);
            }
            this.value=(Number)value;
            valueJLabel.setText(value.toString());
            updateColor();
        }
    }

    @Override
    final public void sendValueToDevice()
    {
        int start=0;
        byte[] buf=new byte[64];
        start=Buffer.setUint16(buf,start,dataIndex);
        start=Buffer.setUint8(buf,start,type.ordinal());
        start=setBuf(buf,start);
        addTailAndSend(buf,start,0X20);
        needSendValueFlag=false;
    }

    abstract protected boolean sameAsValue(Object v);

    abstract public int setBuf(byte[] buf,int start);

    @Override
    public String toString()
    {
        return value.toString();
    }
}
